﻿using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
using UnityEngine.EventSystems;

public struct HitResult{
	public bool isUI;
	public float distance;
	public Vector3 point;
	public GameObject hitObj;
};
/// <summary>
/// 此脚本负责管理玩家和物体之间的一切交互事件
/// </summary>
public class InteractionManager : MonoBehaviour {
	///脚本本身
	public static InteractionManager _instance;

	[SerializeField] string centerPointName = "CenterPoint";
	Transform centerPoint;
	///当objGazed==null时，中心点放置的距离
	[SerializeField] float disWhileNull = 10f;

	///被凝视的物体
	public GameObject ObjGazed{
		get{ 
			return hitResult.hitObj;
		}
	}
	///被凝视物体到主摄像机的距离
	public float Distance{
		get{ return (hitResult.distance);}
	}
	///当objGazed==null时，中心点放置的距离
	public float DisWhileNull{
		get{ return disWhileNull;}
	}

	RaycastHit hit;
	HitResult hitResult;

	Transform mCamera;

	///上一次获取被凝视物体时的时间
	float curTime = -1f;

	///中心点的原始比例大小
	Vector3 regionScale;

	void Awake(){
		InteractionManager._instance = this;
	}

	void Start(){
		centerPoint = ItemManager.GetItemFlag (centerPointName).transform;
		mCamera = Camera.main.transform;
		regionScale = centerPoint.localScale;
	}

	//void OnInteraction(RaycastHit hit)
	/// <summary>
	/// 交互函数，当物体与玩家产生交互时
	/// </summary>
	/// <param name="hit">Hit.</param>
	void OnInteraction(RaycastHit hit){
		
	}

	void LateUpdate () {
		RayCast ();
		centerPoint.position = hitResult.point;
		centerPoint.localScale = regionScale * hitResult.distance / disWhileNull;
		centerPoint.LookAt (centerPoint.position * 2 - mCamera.position);
		if (MyInput.GetInputOfType (InputType.CONFIRM)) {
			GameObject objGazed = hitResult.hitObj;
			print (objGazed);
			if (hitResult.hitObj != null) {
				if (hitResult.isUI) {
					Button bt = hitResult.hitObj.GetComponent<Button> ();
					if (bt != null) {
						//bt.onClick.Invoke ();
					}
				} else {
					objGazed.SendMessage ("OnInteraction", hit, SendMessageOptions.DontRequireReceiver);
					if (objGazed.transform.parent != null) {
						objGazed.transform.parent.SendMessage ("OnInteraction", hit, SendMessageOptions.DontRequireReceiver);
					}
				}
			}
		}
	}

	/// <summary>
	/// 用射线检测场景，可能检测到的是3D物体，也可能是UI
	/// 信息存储到hitResult中
	/// </summary>
	void RayCast(){
		Ray ray = new Ray (mCamera.position, mCamera.forward);
		if (Physics.Raycast (ray, out hit, disWhileNull, LayerMask.NameToLayer("Player"))) {
			hitResult.point = hit.point;
			hitResult.hitObj = hit.transform.gameObject;
			hitResult.distance = hit.distance;
		} else {
			hitResult.point = mCamera.position + mCamera.forward * disWhileNull;
			hitResult.hitObj = null;
			hitResult.distance = disWhileNull;
		}
		hitResult.isUI = false;
		foreach (RaycastResult rr in GetUIRaycast(hitResult.point)) {
			if (rr.gameObject.GetComponent<Button>() != null && rr.distance <= hitResult.distance) {
				hitResult.isUI = true;
				hitResult.distance = rr.distance + Camera.main.nearClipPlane;
				hitResult.point = mCamera.position + (hitResult.point - mCamera.position).normalized * hitResult.distance;
				hitResult.hitObj = rr.gameObject;
				//print (hitResult.distance.ToString () + "---" + Vector3.Distance (hitResult.hitObj.transform.position, mCamera.position).ToString ());
			}
			/*Button bt = rr.gameObject.GetComponent<Button> ();
			if (bt != null) {
				bt.onClick.Invoke ();
			}*/
		}
	}
	/// <summary>
	/// 用 从主摄像机到lookPoint 的射线检测场景中的所有UI
	/// 返回UI中hitPoint点的所有UI物体
	/// </summary>
	/// <returns>The user interface raycast.</returns>
	/// <param name="lookPoint">Look point.</param>
	List<RaycastResult> GetUIRaycast(Vector3 lookPoint){
		if (centerPoint == null) {
			return null;
		}
		Vector3 screenPos = Camera.main.WorldToScreenPoint (lookPoint);
		Vector2 screenPos2 = new Vector2 (screenPos.x, screenPos.y);
		List<RaycastResult> rrs = new List<RaycastResult> ();
		PointerEventData ped = new PointerEventData (EventSystem.current);
		ped.position = screenPos2;
		foreach (GraphicRaycaster gr in GameObject.FindObjectsOfType<GraphicRaycaster>()) {
			gr.Raycast (ped, rrs);
		}
		return rrs;
	}

	//是否显示射线
	[SerializeField] bool isShowLine = true;
	void OnDrawGizmos(){
		if (isShowLine) {
			DrawRayToCenterPoint ();
		}
	}
	void DrawRayToCenterPoint(){
		if (centerPoint != null) {
			Gizmos.DrawLine (Camera.main.transform.position, centerPoint.position);
		}
	}

}
